﻿/*
 * Copyright 2010-2013 Team Robot, Inc.
 * 
 * Author: Peter Coley
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace TeamRobot
{
    /// <summary>
    /// Some simple wrapper methods on json.net that handle common settings for Team Robot code.
    /// </summary>
    public static class JsonUtility
    {
        public static string SerializeObject(object data)
        {
            return SerializeObject(data, false, true, true);
        }

        public static string SerializeObject(object data, bool indent)
        {
            return SerializeObject(data, indent, true, true);
        }

        public static string SerializeObject(object data, bool indent, bool ignoreNulls, bool ignoreDefaults)
        {
            var converters = new List<JsonConverter>();
            converters.Add(new StringEnumConverter());
            return JsonConvert.SerializeObject(data,
                indent ? Formatting.Indented : Formatting.None,
                new JsonSerializerSettings
                {
                    NullValueHandling = ignoreNulls ? NullValueHandling.Ignore : NullValueHandling.Include,
                    DefaultValueHandling = ignoreDefaults ? DefaultValueHandling.Ignore : DefaultValueHandling.Include,
                    DateTimeZoneHandling = DateTimeZoneHandling.Utc,
                    Converters = converters
                });
        }

        public static T DeserializeObject<T>(string data)
        {
            return JsonConvert.DeserializeObject<T>(data, new JsonSerializerSettings
            {
                Converters = new List<JsonConverter> { new StringEnumConverter() },
                DateTimeZoneHandling = DateTimeZoneHandling.Utc,
                NullValueHandling = NullValueHandling.Ignore,
                DefaultValueHandling = DefaultValueHandling.Populate,
            });
        }

        public static T DeserializeObject<T>(Stream stream)
        {
            var formatter = new JsonSerializer();
            formatter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
            formatter.Converters.Add(new StringEnumConverter());
            formatter.NullValueHandling = NullValueHandling.Ignore;
            formatter.DefaultValueHandling = DefaultValueHandling.Populate;

            var tr = new StreamReader(stream);
            return (T)formatter.Deserialize(tr, typeof(T));
        }

        public static Stream SerializeObjectToStream(object data)
        {
            var formatter = new JsonSerializer();
            formatter.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
            formatter.Converters.Add(new StringEnumConverter());
            formatter.NullValueHandling = NullValueHandling.Ignore;
            formatter.DefaultValueHandling = DefaultValueHandling.Ignore;

            MemoryStream ms = new MemoryStream();
            var tw = new StreamWriter(ms);
            formatter.Serialize(tw, data);
            tw.Flush();
            ms.Seek(0, SeekOrigin.Begin);

            return ms;
        }
    }
}
